﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComplexNumbers
{
    class ComplexNumber
    {
        private double real;
        private double imag;

        public double Real
        {
            get { return real; }
            set { real = value; }
        }

        public double Imag
        {
            get { return imag; }
            set { imag = value; }
        }

        public ComplexNumber(double real, double imag)
        {
            this.real = real;
            this.imag = imag;
        }

        public static ComplexNumber operator +(ComplexNumber complex1, ComplexNumber complex2)
        {
            double real = complex1.real + complex2.real;
            double imag = complex1.imag + complex2.imag;
            return new ComplexNumber(real, imag);
        }

        public static ComplexNumber operator -(ComplexNumber complex1, ComplexNumber complex2)
        {
            double real = complex1.real - complex2.real;
            double imag = complex1.imag - complex2.imag;
            return new ComplexNumber(real, imag);
        }

        public static ComplexNumber operator *(ComplexNumber complex1, ComplexNumber complex2)
        {
            double real = complex1.real * complex2.real - complex1.imag * complex2.imag;
            double imag = complex1.imag * complex2.real + complex2.imag * complex1.real;
            return new ComplexNumber(real, imag);
        }
        
        public static ComplexNumber operator /(ComplexNumber complex1, ComplexNumber complex2)
        {
            if ((complex2.real * complex2.real + complex2.imag * complex2.imag) != 0)
            {
                double real = (complex1.real * complex2.real + complex1.imag * complex2.imag) /
                    (complex2.real * complex2.real + complex2.imag * complex2.imag);
                double imag = (complex1.imag * complex2.real - complex2.imag * complex1.real) /
                    (complex2.real * complex2.real + complex2.imag * complex2.imag);
                return new ComplexNumber(real, imag);
            }
            else
            {
                return double.NaN;
            }           
        }

        public static implicit operator ComplexNumber(double number)
        {
            return new ComplexNumber(number, 0);
        }

        public static explicit operator double(ComplexNumber complex)
        {
            if (complex.imag != 0)
            {
                return double.NaN;
            }
            else
            {
                //return Math.Sqrt(complex.real * complex.real + complex.imag * complex.imag);
                return complex.real;
            }
        }

        public override string ToString()
        {
            if (this.real == double.NaN)
            {
                return double.NaN.ToString();
            }
            else
            {
                if (this.imag >= 0)
                {
                    return String.Format("{0} + i{1}", this.real, this.imag);
                }
                else
                {
                    return String.Format("{0} - i{1}", this.real, Math.Abs(this.imag));
                }
            }
        }

        public double this[int index]
        {
            get 
            {
                if (index != 0 && index != 1)
                {
                    throw new IndexOutOfRangeException(String.Format("Index must be 0 or 1, not {0}", index));
                }
                else
                {
                    if (index == 0)
                    {
                        return this.real;
                    }
                    else
                    {
                        if (index == 1)
                        {
                            return this.imag;
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                    }
                }
            }
            set
            {
                if (index != 0 && index != 1)
                {
                    throw new IndexOutOfRangeException(String.Format("Index must be 0 or 1, not {0}", index));
                }
                else
                {
                    if (index == 0)
                    {
                        this.real = value;
                    }
                    else
                    {
                        if (index == 1)
                        {
                            this.imag = value;
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                    }
                }
            }
        }
    }
}
